home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / lfs / lfsSegUsage.c < prev    next >
C/C++ Source or Header  |  1991-08-08  |  33KB  |  1,159 lines

  1. /* 
  2.  * lfsSegUsage.c --
  3.  *
  4.  *    Routines and data structures providing knowledge more segments 
  5.  *    block usage.  This module managers the segment usage array and
  6.  *    implements the selection of the next segment to write and to
  7.  *    clean.  This module should be notified of all block deallocation
  8.  *    inorder to make intelligent choices.  The module also detects 
  9.  *    "logwrap" and starts with block cleaner and generates "df"
  10.  *    numbers.
  11.  *
  12.  *     For each LFS, the module classifies segment into one of three classes:
  13.  *    clean, dirty, or full.   A segment is clean if it
  14.  *    contains no live data.  A segment is dirty if it is not clean
  15.  *    and has fewer activeBytes than permitable. A segment is full if
  16.  *    it is neither clean nor dirty.
  17.  *
  18.  * Copyright 1989 Regents of the University of California
  19.  * Permission to use, copy, modify, and distribute this
  20.  * software and its documentation for any purpose and without
  21.  * fee is hereby granted, provided that the above copyright
  22.  * notice appear in all copies.  The University of California
  23.  * makes no representations about the suitability of this
  24.  * software for any purpose.  It is provided "as is" without
  25.  * express or implied warranty.
  26.  */
  27.  
  28. #ifndef lint
  29. static char rcsid[] = "$Header: /sprite/src/kernel/lfs/RCS/lfsSegUsage.c,v 1.14 91/08/08 17:49:54 mendel Exp $ SPRITE (Berkeley)";
  30. #endif /* not lint */
  31.  
  32. #include <lfsInt.h>
  33. #include <lfsSeg.h>
  34. #include <lfsStableMemInt.h>
  35. #include <lfsSegUsageInt.h>
  36.  
  37. #include <fsdm.h>
  38.  
  39. int lfsMinCleanThreshold = 5;
  40.  
  41. /*
  42.  *----------------------------------------------------------------------
  43.  *
  44.  * LfsSegUsageFreeBlocks --
  45.  *
  46.  *    Inform the segment usage manager that blocks are no long needed.
  47.  *
  48.  * Results:
  49.  *    SUCCESS if the blocks are valid.
  50.  *
  51.  * Side effects:
  52.  *    Seg usage map.
  53.  *
  54.  *----------------------------------------------------------------------
  55.  */
  56.  
  57. ReturnStatus
  58. LfsSegUsageFreeBlocks(lfsPtr, blockSize, blockArrayLen, blockArrayPtr)
  59.     Lfs        *lfsPtr;    /* File system of interest. */
  60.     int        blockSize;    /* Size in bytes of blocks to free. */
  61.     int             blockArrayLen; /* Number of elements in blockArrayPtr. */
  62.     LfsDiskAddr *blockArrayPtr;            /* Array of disk addresses. */
  63. {
  64.     int        i;
  65.     LfsDiskAddr    diskAddress;
  66.  
  67.     for (i = 0; i < blockArrayLen; i++) {
  68.     diskAddress = *blockArrayPtr;
  69.     if (!LfsIsNilDiskAddr(diskAddress)) {
  70.         LfsSetNilDiskAddr(blockArrayPtr);
  71.         LFS_STATS_INC(lfsPtr->stats.segusage.blocksFreed);
  72.         LFS_STATS_ADD(lfsPtr->stats.segusage.bytesFreed,  blockSize);
  73.         LfsSetSegUsage(lfsPtr,
  74.         LfsDiskAddrToSegmentNum(lfsPtr, diskAddress), -blockSize);
  75.     }
  76.     blockArrayPtr++;
  77.     }
  78.     return SUCCESS;
  79. }
  80.  
  81. /*
  82.  *----------------------------------------------------------------------
  83.  *
  84.  * SegUsageAllocateBytes --
  85.  *
  86.  *    Inform the file system for the need to allocate some bytes.
  87.  *
  88.  * Results:
  89.  *    SUCCESS if the allocation works, failure otherwise.
  90.  *
  91.  * Side effects:
  92.  *    
  93.  *
  94.  *----------------------------------------------------------------------
  95.  */
  96. ReturnStatus 
  97. LfsSegUsageAllocateBytes(lfsPtr, numBytes)
  98.        Lfs    *lfsPtr;    /* File system of interest. */
  99.        int    numBytes;       /* Number of file system bytes needed. */
  100. {
  101.     LfsSegUsage *usagePtr = &(lfsPtr->usageArray);
  102.     LfsSegUsageCheckPoint *cp = &(usagePtr->checkPoint);
  103.     int blocks;
  104.  
  105.     blocks = LfsBytesToBlocks(lfsPtr, numBytes);
  106.     if (cp->freeBlocks - blocks > usagePtr->params.minFreeBlocks) { 
  107.     return SUCCESS;
  108.     }
  109.     return FS_NO_DISK_SPACE;
  110. }
  111.  
  112. /*
  113.  *----------------------------------------------------------------------
  114.  *
  115.  * SegUsageFreeBytes --
  116.  *
  117.  *    Inform the file system that the previously allocated bytes are 
  118.  *    nolonger needed or have already been allocated on disk.
  119.  *
  120.  * Results:
  121.  *    SUCCESS if the allocation works, failure otherwise.
  122.  *
  123.  * Side effects:
  124.  *    
  125.  *
  126.  *----------------------------------------------------------------------
  127.  */
  128. ReturnStatus 
  129. LfsSegUsageFreeBytes(lfsPtr,numBytes)
  130.        Lfs    *lfsPtr;    /* File system of interest. */
  131.        int    numBytes;       /* Number of file system bytes to free. */
  132. {
  133.     return SUCCESS;
  134. }
  135.  
  136. /*
  137.  *----------------------------------------------------------------------
  138.  *
  139.  * LfsCheckRead --
  140.  *
  141.  *    Check to see if it is ok to read the specified byte range. 
  142.  *
  143.  * Results:
  144.  *
  145.  * Side effects:
  146.  *    
  147.  *
  148.  *----------------------------------------------------------------------
  149.  */
  150. void
  151. LfsCheckRead(lfsPtr,diskAddress, numBytes)
  152.        Lfs    *lfsPtr;    /* File system of interest. */
  153.        LfsDiskAddr   diskAddress;  /* Disk address of read. */
  154.        int    numBytes;          /* Number of bytes being read. */
  155. {
  156.     LfsSegUsage *usagePtr = &(lfsPtr->usageArray);
  157.     register LfsSegUsageEntry  *s;
  158.     int segNo, segNo2, blocks;
  159.     ReturnStatus      status;
  160.     LfsDiskAddr newDiskAddr;
  161.     LfsStableMemEntry smemEntry;
  162.  
  163.     segNo = LfsDiskAddrToSegmentNum(lfsPtr, diskAddress);
  164.     if ((segNo < 0) || (segNo >=  usagePtr->params.numberSegments)) {
  165.     panic("LfsOkToRead bad segment number %d\n", segNo);
  166.     return;
  167.     }
  168.     status = LfsStableMemFetch(&(usagePtr->stableMem),segNo,0,&smemEntry);
  169.     if (status != SUCCESS) {
  170.     panic("LfsOkToRead can't fetch usage array block.\n");
  171.     }
  172.     s = (LfsSegUsageEntry *) LfsStableMemEntryAddr(&smemEntry);
  173.  
  174.     if (s->flags & LFS_SEG_USAGE_CLEAN) {
  175.     panic("LfsOkToRead read from clean segment\n");
  176.     LfsStableMemRelease(&(usagePtr->stableMem), &smemEntry, FALSE);
  177.     return;
  178.     }
  179.     LfsStableMemRelease(&(usagePtr->stableMem), &smemEntry, FALSE);
  180.     blocks = LfsBytesToBlocks(lfsPtr, numBytes)-1;
  181.     LfsDiskAddrPlusOffset(diskAddress, blocks, &newDiskAddr);
  182.     segNo2 = LfsDiskAddrToSegmentNum(lfsPtr, newDiskAddr);
  183.     if (segNo2 != segNo) {
  184.     printf("LfsOkToRead read over segment boundary.\n");
  185.     }
  186.  
  187. }
  188.  
  189. /*
  190.  *----------------------------------------------------------------------
  191.  *
  192.  * LfsSetSegUsage --
  193.  *
  194.  *    Set the usage level of the specified segment.
  195.  *
  196.  * Results:
  197.  *    None
  198.  *
  199.  * Side effects:
  200.  *    Seg usage array may be modified.
  201.  *
  202.  *----------------------------------------------------------------------
  203.  */
  204.  
  205. void
  206. LfsSetSegUsage(lfsPtr, segNumber, activeBytes)
  207.     Lfs        *lfsPtr;    /* File system of interest. */
  208.     int        segNumber;     /* Segment number in file system. */
  209.     int        activeBytes;    /* Usage level Change. */
  210. {
  211.     LfsSegUsage *usagePtr = &(lfsPtr->usageArray);
  212.     LfsSegUsageCheckPoint *cp = &(usagePtr->checkPoint);
  213.     register LfsSegUsageEntry *s;
  214.     ReturnStatus      status;
  215.     LfsStableMemEntry smemEntry;
  216.  
  217.     LFS_STATS_INC(lfsPtr->stats.segusage.usageSet);
  218.     if ((segNumber < 0) || (segNumber >= usagePtr->params.numberSegments)) {
  219.     panic("LfsSetSegUsage bad segment number %d\n", segNumber);
  220.     return;
  221.     }
  222.     if (activeBytes == 0) {
  223.     printf("LfsSetSegUsage: SegNo %d activeBytes %d\n", segNumber, 
  224.             activeBytes);
  225.     }
  226.     /*
  227.      * We special case the current segment we are writing to.
  228.      */
  229.     if (segNumber == cp->currentSegment) {
  230.     int oldActiveBytes = cp->curSegActiveBytes;
  231.     cp->curSegActiveBytes += activeBytes;
  232.     if (cp->curSegActiveBytes < 0) {
  233.          printf("LfsSetSegUsage: Warning activeBytes for segment %d is %d\n",
  234.             segNumber, cp->curSegActiveBytes);
  235.         cp->curSegActiveBytes = 0;
  236.     }
  237.     cp->freeBlocks += (LfsBytesToBlocks(lfsPtr, oldActiveBytes) - 
  238.                LfsBytesToBlocks(lfsPtr, cp->curSegActiveBytes));
  239.     return;
  240.     }
  241.     status = LfsStableMemFetch(&(usagePtr->stableMem), segNumber, 
  242.                 LFS_STABLE_MEM_MAY_DIRTY, &smemEntry);
  243.     if (status != SUCCESS) {
  244.     panic("LfsSetSegUsage can't fetch usage array block.\n");
  245.     return;
  246.     }
  247.     s = (LfsSegUsageEntry *) LfsStableMemEntryAddr(&smemEntry);
  248.  
  249.  
  250.     activeBytes = s->activeBytes + activeBytes;
  251.     if (activeBytes < 0) {
  252.      printf("LfsSetSegUsage: Warning activeBytes for segment %d is %d\n",
  253.         segNumber, activeBytes);
  254.     activeBytes = 0;
  255.     }
  256.     cp->freeBlocks += (LfsBytesToBlocks(lfsPtr, s->activeBytes) - 
  257.                 LfsBytesToBlocks(lfsPtr, activeBytes));
  258.     if (s->flags & LFS_SEG_USAGE_CLEAN) {
  259.     panic("LfsSetSegUsage called on a clean segment (%d)\n", segNumber);
  260.     LfsStableMemRelease(&(usagePtr->stableMem), &smemEntry, FALSE);
  261.     return;
  262.     }
  263.     /*
  264.      * Is it moving onto dirty list?
  265.      */
  266.     if (activeBytes <= cp->dirtyActiveBytes) {
  267.     if (s->flags & LFS_SEG_USAGE_DIRTY) { 
  268.         /*
  269.          * All ready on dirty list then do nothing.
  270.          */
  271.         s->activeBytes = activeBytes;
  272.         LfsStableMemRelease(&(usagePtr->stableMem), &smemEntry, TRUE);
  273.         return;
  274.     }
  275.         s->activeBytes = activeBytes;
  276.     s->flags |= LFS_SEG_USAGE_DIRTY;
  277.     cp->numDirty++;
  278.     LfsStableMemRelease(&(usagePtr->stableMem), &smemEntry, TRUE);
  279.     return;
  280.     }
  281.     /*
  282.      * Segment is not clean or dirty just full.
  283.      */
  284.     if (s->flags & LFS_SEG_USAGE_DIRTY) { 
  285.     s->flags &= ~LFS_SEG_USAGE_DIRTY;
  286.     cp->numDirty--;
  287.     }
  288.     s->activeBytes = activeBytes;
  289.     LfsStableMemRelease(&(usagePtr->stableMem), &smemEntry, TRUE);
  290.  
  291. }
  292.  
  293. /*
  294.  *----------------------------------------------------------------------
  295.  *
  296.  * LfsMarkSegsClean --
  297.  *
  298.  *    Mark the specified segments as clean.
  299.  *
  300.  * Results:
  301.  *    None
  302.  *
  303.  * Side effects:
  304.  *    Seg usage array may be modified.
  305.  *
  306.  *----------------------------------------------------------------------
  307.  */
  308.  
  309. void
  310. LfsMarkSegsClean(lfsPtr, numSegs, segs)
  311.     Lfs        *lfsPtr;    /* File system of interest. */
  312.     int        numSegs;     /* Number of segments in list. */
  313.     LfsSegList    *segs;        /* Segments to mark clean. */
  314. {
  315.     LfsSegUsage *usagePtr = &(lfsPtr->usageArray);
  316.     LfsSegUsageCheckPoint *cp = &(usagePtr->checkPoint);
  317.     register LfsSegUsageEntry  *s;
  318.     int            i, segNumber, first, previous, flags, nextSeg;
  319.     ReturnStatus      status;
  320.     LfsStableMemEntry smemEntry;
  321.  
  322.     /*
  323.      * Build a list of the segment to mark clean. 
  324.      */
  325.     first = previous = -1;
  326.     flags = LFS_STABLE_MEM_MAY_DIRTY;
  327.     for (i = 0; i < numSegs; i++) {
  328.     if (segs[i].segNumber == -1) {
  329.         /*
  330.          * Segments get marked with -1 if we can't clean them.
  331.          */
  332.         continue;
  333.     }
  334.     segNumber = segs[i].segNumber;
  335.  
  336.     status = LfsStableMemFetch(&(usagePtr->stableMem), segNumber, 
  337.                 flags, &smemEntry);
  338.     if (status != SUCCESS) {
  339.         panic("LfsMarkSegClean can't fetch segment %d usage array.",
  340.             segNumber);
  341.         return;
  342.     }
  343.     flags |= LFS_STABLE_MEM_REL_ENTRY;
  344.     s = (LfsSegUsageEntry *) LfsStableMemEntryAddr(&smemEntry);
  345.     if (s->flags & LFS_SEG_USAGE_CLEAN) { 
  346.         /*
  347.          * Already clean, skip it.
  348.          */
  349.         continue;
  350.     }
  351.     /*
  352.      * Segment is being marked clean. Remove from dirty list if necessary.
  353.      */
  354.     if (s->flags & LFS_SEG_USAGE_DIRTY) { 
  355.         s->flags &= ~LFS_SEG_USAGE_DIRTY;
  356.         cp->numDirty--;
  357.     }
  358.     cp->numClean++;
  359.     s->flags = LFS_SEG_USAGE_CLEAN;
  360.     s->activeBytes = previous;
  361.     LfsStableMemMarkDirty(&smemEntry);
  362.     if (previous == -1) {
  363.         first = segNumber;
  364.     }
  365.     previous = segNumber;
  366.     }
  367.  
  368.     if (previous == -1) {
  369.     /*
  370.      * Nothing to clean. 
  371.      */
  372.     return;
  373.     }
  374.  
  375.     /*
  376.      * Insert the new list into the list of already clean
  377.      * segments. We insert this segment as the second element on
  378.      * the list.  This requires two Fetchs:
  379.      * 1) Update the head of list segment to point at us.
  380.      * 2) Update us to point at what the head of list use to.
  381.      */
  382.     status = LfsStableMemFetch(&(usagePtr->stableMem), cp->cleanSegList, 
  383.             flags, &smemEntry);
  384.     if (status != SUCCESS) {
  385.     panic("LfsMarkSegClean can't fetch usage array.");
  386.     return;
  387.     }
  388.     s = (LfsSegUsageEntry *) LfsStableMemEntryAddr(&smemEntry);
  389.     nextSeg = s->activeBytes;
  390.     s->activeBytes = previous;
  391.     LfsStableMemMarkDirty(&smemEntry);
  392.  
  393.     status = LfsStableMemFetch(&(usagePtr->stableMem), first, 
  394.             LFS_STABLE_MEM_MAY_DIRTY|LFS_STABLE_MEM_REL_ENTRY, 
  395.             &smemEntry);
  396.     if (status != SUCCESS) {
  397.     panic("LfsMarkSegClean can't fetch usage array.");
  398.     return;
  399.     }
  400.     s = (LfsSegUsageEntry *) LfsStableMemEntryAddr(&smemEntry);
  401.     s->activeBytes = nextSeg;
  402.     LfsStableMemRelease(&(usagePtr->stableMem), &smemEntry, TRUE);
  403.     return;
  404. }
  405.  
  406. /*
  407.  *----------------------------------------------------------------------
  408.  *
  409.  * LfsSetDirtyLevel --
  410.  *
  411.  *    Set the usage level below which a segment is considered dirty.
  412.  *
  413.  * Results:
  414.  *    None
  415.  *
  416.  * Side effects:
  417.  *    Seg usage array may be modified.
  418.  *
  419.  *----------------------------------------------------------------------
  420.  */
  421.  
  422. void
  423. LfsSetDirtyLevel(lfsPtr, dirtyActiveBytes)
  424.     Lfs    *lfsPtr;
  425.     int     dirtyActiveBytes; /* New level. */
  426. {
  427.     LfsSegUsage *usagePtr = &(lfsPtr->usageArray);
  428.     LfsSegUsageCheckPoint *cp = &(usagePtr->checkPoint);
  429.     register LfsSegUsageEntry  *s;
  430.     register int    segNum;
  431.     ReturnStatus      status;
  432.     LfsStableMemEntry smemEntry;
  433.  
  434.  
  435.     cp->dirtyActiveBytes = dirtyActiveBytes;
  436.     for (segNum = 0; segNum < usagePtr->params.numberSegments; segNum++) {
  437.     status = LfsStableMemFetch(&(usagePtr->stableMem), segNum,
  438.             LFS_STABLE_MEM_MAY_DIRTY| 
  439.               ((segNum > 0) ? LFS_STABLE_MEM_REL_ENTRY : 0), 
  440.               &smemEntry);
  441.  
  442.     if (status != SUCCESS) {
  443.         panic("LfsSetDirtyLevel can't fetch usage array block.\n");
  444.     }
  445.      s = (LfsSegUsageEntry *) LfsStableMemEntryAddr(&smemEntry);
  446.     if (s->activeBytes <= dirtyActiveBytes) {
  447.         if (s->flags & (LFS_SEG_USAGE_DIRTY|LFS_SEG_USAGE_CLEAN)) { 
  448.         /*
  449.          * All ready on dirty or clean list then do nothing.
  450.          */
  451.         } else { 
  452.         s->flags |= LFS_SEG_USAGE_DIRTY;
  453.         cp->numDirty++;
  454.         LfsStableMemMarkDirty(&smemEntry);
  455.         }
  456.     } 
  457.     }
  458.     LfsStableMemRelease(&(usagePtr->stableMem), &smemEntry, FALSE);
  459.  
  460. }
  461.  
  462.  
  463. /*
  464.  *----------------------------------------------------------------------
  465.  *
  466.  * Lfs_DomainInfo --
  467.  *
  468.  *    Return info about the given domain lfsDomain.
  469.  *
  470.  * Results:
  471.  *    SUCCESS
  472.  *
  473.  * Side effects:
  474.  *    The domain info struct is filled in.
  475.  *
  476.  *----------------------------------------------------------------------
  477.  */
  478. ReturnStatus
  479. Lfs_DomainInfo(domainPtr, domainInfoPtr)
  480.     Fsdm_Domain    *domainPtr;
  481.     Fs_DomainInfo    *domainInfoPtr;
  482. {
  483.     Lfs        *lfsPtr = LfsFromDomainPtr(domainPtr);
  484.     LfsSegUsage *usagePtr = &(lfsPtr->usageArray);
  485.     LfsSegUsageCheckPoint *cp = &(usagePtr->checkPoint);
  486.     int        numSegAvail, numBlocksAvail;
  487.  
  488.     /*
  489.      * Compute the number of segments available for blocks.
  490.      */
  491.     numSegAvail = usagePtr->params.numberSegments - 
  492.                 usagePtr->params.minNumClean;
  493.  
  494.     domainInfoPtr->maxKbytes = (LfsSegSize(lfsPtr)/1024) * numSegAvail;
  495.  
  496.     /*
  497.      * Compute the number of block available.
  498.      */
  499.     numBlocksAvail = cp->freeBlocks - usagePtr->params.minFreeBlocks;
  500.     if (numBlocksAvail < 0) {
  501.     numBlocksAvail = 0;
  502.     }
  503.  
  504.     domainInfoPtr->freeKbytes = LfsBlocksToBytes(lfsPtr, numBlocksAvail) / 1024;
  505.  
  506.     domainInfoPtr->maxFileDesc = lfsPtr->descMap.params.maxDesc;
  507.     domainInfoPtr->freeFileDesc = lfsPtr->descMap.params.maxDesc -
  508.                   lfsPtr->descMap.checkPoint.numAllocDesc;
  509.     domainInfoPtr->blockSize = FS_BLOCK_SIZE;
  510.     domainInfoPtr->optSize = FS_BLOCK_SIZE;
  511.  
  512.  
  513.     return(SUCCESS);
  514. }
  515.  
  516.  
  517.  
  518. /*
  519.  *----------------------------------------------------------------------
  520.  *
  521.  * LfsGetLogTail --
  522.  *
  523.  *    Get the next available clean blocks to write the log to.
  524.  *
  525.  * Results:
  526.  *    SUCCESS if log space was retrieved. FS_NO_DISK_SPACE if log
  527.  *    space is not available. FS_WOULD_BLOCK if operation of blocked.
  528.  *
  529.  * Side effects:
  530.  *
  531.  *
  532.  *----------------------------------------------------------------------
  533.  */
  534.  
  535. ReturnStatus
  536. LfsGetLogTail(lfsPtr, cantWait, logRangePtr, startBlockPtr)
  537.     Lfs    *lfsPtr;    /* File system of interest. */
  538.     Boolean    cantWait;      /* TRUE if we can't wait for a clean seg. */
  539.     LfsSegLogRange *logRangePtr;  /* Segments numbers returned. */
  540.     int           *startBlockPtr; /* OUT: Starting offset into segment. */
  541. {
  542.     LfsSegUsage *usagePtr = &(lfsPtr->usageArray);
  543.     LfsSegUsageCheckPoint *cp = &(usagePtr->checkPoint);
  544.     LfsSegUsageEntry *s;
  545.     int        segNumber;
  546.     ReturnStatus      status;
  547.     LfsStableMemEntry smemEntry;
  548.  
  549.  
  550.     if (!cantWait && 
  551.     (cp->numClean <= 
  552.         lfsPtr->usageArray.params.minNumClean + lfsMinCleanThreshold)) {
  553.     LfsSegCleanStart(lfsPtr);
  554.     if (cp->numClean <= lfsPtr->usageArray.params.minNumClean) {
  555.         return FS_WOULD_BLOCK;
  556.     }
  557.     }
  558.     if (cp->currentBlockOffset != -1) {
  559.     /*
  560.      * There is still room in the existing segment. Use it.
  561.      */
  562.     logRangePtr->prevSeg = cp->previousSegment;
  563.     logRangePtr->current = cp->currentSegment;
  564.     logRangePtr->nextSeg =  cp->cleanSegList;
  565.     (*startBlockPtr) = cp->currentBlockOffset;
  566.     return SUCCESS;
  567.     }
  568.     /*
  569.      * Need to location a new segment.
  570.      */
  571.     if (cp->numClean == 0) {
  572.     return FS_NO_DISK_SPACE;
  573.     }
  574.     /*
  575.      * Update the active bytes of the current segment the usage array.
  576.      */
  577.     status = LfsStableMemFetch(&(usagePtr->stableMem), cp->currentSegment, 
  578.             LFS_STABLE_MEM_MAY_DIRTY, &smemEntry);
  579.     if (status == SUCCESS) {
  580.     s = (LfsSegUsageEntry *) LfsStableMemEntryAddr(&smemEntry);
  581.     s->activeBytes = cp->curSegActiveBytes;
  582.     if (s->activeBytes <= cp->dirtyActiveBytes) {
  583.         s->flags |= LFS_SEG_USAGE_DIRTY;
  584.         cp->numDirty++;
  585.     }
  586.     s->timeOfLastWrite = usagePtr->timeOfLastWrite;
  587.     LfsStableMemMarkDirty(&smemEntry);
  588.     } else {
  589.     panic("LfsGetCleanSeg can't fetch usage array.");
  590.     }
  591.  
  592.     segNumber = cp->cleanSegList;
  593.     status = LfsStableMemFetch(&(usagePtr->stableMem), segNumber, 
  594.             (LFS_STABLE_MEM_MAY_DIRTY| 
  595.              LFS_STABLE_MEM_REL_ENTRY), &smemEntry);
  596.     if (status != SUCCESS) {
  597.     panic("LfsGetCleanSeg can't fetch usage array.");
  598.     return status;
  599.     }
  600.  
  601.     s = (LfsSegUsageEntry *) LfsStableMemEntryAddr(&smemEntry);
  602.     cp->cleanSegList = s->activeBytes;
  603.  
  604.     logRangePtr->prevSeg = cp->previousSegment = cp->currentSegment;
  605.     logRangePtr->current = cp->currentSegment = segNumber;
  606.     logRangePtr->nextSeg =  cp->cleanSegList;
  607.  
  608.     usagePtr->timeOfLastWrite = 0;
  609.     cp->numClean--;
  610.     s->activeBytes = cp->curSegActiveBytes = 0;
  611.     if (cp->numClean <= lfsPtr->usageArray.params.minNumClean) {
  612.     LfsSegCleanStart(lfsPtr);
  613.     }
  614.     s->flags  &= ~LFS_SEG_USAGE_CLEAN;
  615.     LfsStableMemRelease(&(usagePtr->stableMem), &smemEntry, TRUE);
  616.     (*startBlockPtr) = 0;
  617.     return SUCCESS;
  618. }
  619.  
  620. /*
  621.  *----------------------------------------------------------------------
  622.  *
  623.  * LfsSetLogTail --
  624.  *
  625.  *    Set the next available clean blocks to write the log to.
  626.  *
  627.  * Results:
  628.  *    None
  629.  *
  630.  * Side effects:
  631.  *
  632.  *
  633.  *----------------------------------------------------------------------
  634.  */
  635.  
  636. void
  637. LfsSetLogTail(lfsPtr, logRangePtr, startBlock, activeBytes, timeOfLastWrite)
  638.     Lfs    *lfsPtr;    /* File system of interest. */
  639.     LfsSegLogRange *logRangePtr;  /* Segments numbers returned. */
  640.     int    startBlock; /* Starting offset into segment. */
  641.     int    activeBytes;    /* Number of bytes written. */
  642.     int    timeOfLastWrite; /* Youngest block in segment. */
  643. {
  644.     LfsSegUsage *usagePtr = &(lfsPtr->usageArray);
  645.     LfsSegUsageCheckPoint *cp = &(usagePtr->checkPoint);
  646.  
  647.     cp->currentBlockOffset = startBlock;
  648.     if (usagePtr->timeOfLastWrite < timeOfLastWrite) {
  649.     usagePtr->timeOfLastWrite = timeOfLastWrite;
  650.     }
  651.     if (activeBytes > 0) {
  652.     LfsSetSegUsage(lfsPtr, logRangePtr->current, activeBytes);
  653.    }
  654. }
  655.  
  656. /*
  657.  *----------------------------------------------------------------------
  658.  *
  659.  * LfsSegUsageEnoughClean --
  660.  *
  661.  *    Check to see if we have enought clean segment to accept this
  662.  *    data.
  663.  *
  664.  * Results:
  665.  *    TRUE if we do. FALSE if call should wait for some to become 
  666.  *    available.
  667.  *
  668.  * Side effects:
  669.  *    None.
  670.  *
  671.  *----------------------------------------------------------------------
  672.  */
  673.  
  674. Boolean
  675. LfsSegUsageEnoughClean(lfsPtr, dirtyBytes)
  676.     Lfs    *lfsPtr;
  677.     int    dirtyBytes;
  678. {
  679.     LfsSegUsage *usagePtr = &(lfsPtr->usageArray);
  680.     LfsSegUsageCheckPoint *cp = &(usagePtr->checkPoint);
  681.     int    segsAvailable, cleaningThreshold;
  682.  
  683.  
  684.     segsAvailable = cp->numClean - usagePtr->params.minNumClean;
  685.     cleaningThreshold = segsAvailable - lfsMinCleanThreshold;
  686.     if (cleaningThreshold * LfsSegSize(lfsPtr) < dirtyBytes) {
  687.     LfsSegCleanStart(lfsPtr);
  688.     }
  689.     return ((segsAvailable * LfsSegSize(lfsPtr)) > dirtyBytes);
  690. }
  691.  
  692. /*
  693.  *----------------------------------------------------------------------
  694.  *
  695.  * LfsGetSegsToClean --
  696.  *
  697.  *    Return a set of segments to clean.
  698.  *
  699.  * Results:
  700.  *    Number of segments returned.
  701.  *
  702.  * Side effects:
  703.  *
  704.  *
  705.  *----------------------------------------------------------------------
  706.  */
  707.  
  708. int
  709. LfsGetSegsToClean(lfsPtr, maxSegArrayLen, segArrayPtr, minNeededToCleanPtr,
  710.           maxAvailToWritePtr)
  711.     Lfs      *lfsPtr;    /* File system of interest. */
  712.     int      maxSegArrayLen;     /* The maximum number of segment to clean to 
  713.                  * return. */
  714.     LfsSegList     *segArrayPtr;    /* Array of length maxSegArrayLen to return
  715.                  * segments to clean. */
  716.     int        *minNeededToCleanPtr; /* OUT: Minimum number of segments
  717.                        * that should be cleaned. 
  718.                        */
  719.     int        *maxAvailToWritePtr; /* OUT: Maximum number of segments
  720.                        * that should be cleaned. Before
  721.                        * marking the segment as clean.
  722.                        */
  723. {
  724.     int    numberSegs, segNum, blockSize;
  725.     Boolean fullClean;
  726.     int i, j, currentTime;
  727.     LfsSegUsageEntry *s;
  728.     LfsSegUsage *usagePtr = &(lfsPtr->usageArray);
  729.     ReturnStatus      status;
  730.     int        flags;
  731.     LfsStableMemEntry smemEntry;
  732.  
  733.     (*minNeededToCleanPtr) = 0;
  734.     (*maxAvailToWritePtr) = 0;
  735.     numberSegs = 0;
  736.     blockSize = LfsBlockSize(lfsPtr);
  737.     /*
  738.      * For each  segment.
  739.      */
  740.    currentTime = Fsutil_TimeInSeconds();
  741.    flags = LFS_STABLE_MEM_MAY_DIRTY;
  742.    for (segNum = 0; segNum < usagePtr->params.numberSegments; segNum++) {
  743.     /*
  744.      * Execpt the one currently being written.
  745.      */
  746.     if (usagePtr->checkPoint.currentSegment == segNum) { 
  747.         continue;
  748.     }
  749.     status = LfsStableMemFetch(&(usagePtr->stableMem), segNum,  flags, 
  750.                      &smemEntry);
  751.     if (status != SUCCESS) {
  752.         panic("LfsSetDirtyLevel can't fetch usage array block.\n");
  753.         return status;
  754.     }
  755.     flags |= LFS_STABLE_MEM_REL_ENTRY;
  756.     s = (LfsSegUsageEntry *)LfsStableMemEntryAddr(&smemEntry);
  757.     /*
  758.      * Find the proper position in the list for this segment.
  759.      */
  760.     /*
  761.      * Patch to fixed up bad activeBytes.
  762.      */
  763.     if (!(s->flags & (LFS_SEG_USAGE_CLEAN|LFS_SEG_USAGE_DIRTY)) &&
  764.          (s->activeBytes <= usagePtr->checkPoint.dirtyActiveBytes)) {
  765.         s->flags |= LFS_SEG_USAGE_DIRTY;
  766.         usagePtr->checkPoint.numDirty++;
  767.     }
  768.     if (s->flags & LFS_SEG_USAGE_DIRTY) {
  769.         int    age;
  770.         unsigned int blocks, priority;
  771.         /*
  772.          * Besure the age in minutes is not totally bogus because of 
  773.          * startup settings or running the system with a bogus time.
  774.          */
  775.         age = (currentTime - s->timeOfLastWrite)/60;
  776.         if (age > 60*24*365*2) {
  777.         /*
  778.          * If the age is greater that 2 years set it to 2 years.
  779.          */
  780.         age = 60*24*365*2;
  781.         } else if (age <= 0) {
  782.         /*
  783.          * If the age is less or equal to zero set it to 1 minute. 
  784.          */
  785.          age = 1;
  786.         }
  787.         /*
  788.          * To do the  priority caluation without using floating
  789.          * point we scale the byte values into block values
  790.          * and scale the age into minutes.
  791.          */
  792.         if (s->activeBytes != 0) { 
  793.         blocks = LfsBytesToBlocks(lfsPtr, s->activeBytes);
  794.         if (s->activeBytes < 0) {
  795.             blocks = 0;
  796.         }
  797.         priority = ((LfsSegSizeInBlocks(lfsPtr) - blocks) * age) /
  798.                 (LfsSegSizeInBlocks(lfsPtr) + blocks);
  799.         } else {
  800.         /*
  801.          * Give zero size segments highest priority.
  802.          */
  803.         priority = 0x7fffffff;
  804.         }
  805.         /*
  806.          * Find the last element in the list with a priority
  807.          * greater the the current segments.
  808.          */
  809.         for (i = numberSegs-1; i >= 0; i--) {
  810.         if (segArrayPtr[i].priority >= priority) {
  811.             break;
  812.         } 
  813.         }
  814.         /*
  815.          * Extend the array if it is not full already.
  816.          * Insert new seg at specified position by moving all others down.
  817.          * Don't do insert if position is after the end of the array.
  818.          */
  819.         if (numberSegs < maxSegArrayLen) {
  820.         numberSegs++;
  821.         }
  822.  
  823.         if (i < numberSegs-1) { 
  824.         for (j = numberSegs-2; j > i; j--) {
  825.             segArrayPtr[j+1] = segArrayPtr[j];
  826.         }
  827.         segArrayPtr[i+1].segNumber = segNum;
  828.         segArrayPtr[i+1].activeBytes = s->activeBytes;
  829.         segArrayPtr[i+1].priority = priority;
  830.         }
  831.     }
  832.    }
  833.    LfsStableMemRelease(&(usagePtr->stableMem), &smemEntry, FALSE);
  834.    fullClean = ((lfsPtr->controlFlags & LFS_CONTROL_CLEANALL) != 0);
  835.    /*
  836.     * Set the minimum number to get us above the numSegsToClean
  837.     * threashold. 
  838.     */
  839.    (*minNeededToCleanPtr) = (usagePtr->params.minNumClean + 
  840.                usagePtr->params.numSegsToClean+1) - 
  841.                 usagePtr->checkPoint.numClean;
  842.    if ((*minNeededToCleanPtr) < 0) {
  843.     (*minNeededToCleanPtr) = 0;
  844.    }
  845.    if (fullClean) {
  846.     (*minNeededToCleanPtr) = numberSegs;
  847.    }
  848.    /*
  849.     * Set the max number to write to use half the minimum number or
  850.     * all but the last 10 - whichever is less.
  851.     */
  852.    (*maxAvailToWritePtr) = usagePtr->params.minNumClean / 2;
  853.    if ((*maxAvailToWritePtr) >= usagePtr->checkPoint.numClean-10) {
  854.        (*maxAvailToWritePtr) = usagePtr->checkPoint.numClean-10;
  855.    }
  856.   return numberSegs;
  857. }
  858.  
  859.  
  860. /*
  861.  *----------------------------------------------------------------------
  862.  *
  863.  * LfsSegUsageCheckpointUpdate --
  864.  *
  865.  *    This routine is used to update fields of the seg usage 
  866.  *    checkpoint that change when the checkpoint itself is 
  867.  *    written to the log.
  868.  *
  869.  * Results:
  870.  *    None.
  871.  *
  872.  * Side effects:
  873.  *    None.
  874.  *
  875.  *----------------------------------------------------------------------
  876.  */
  877.  
  878. void
  879. LfsSegUsageCheckpointUpdate(lfsPtr, checkPointPtr, size)
  880.     Lfs     *lfsPtr;     /* File system being checkpointed. */
  881.     char *checkPointPtr; /* Checkpoint region for SegUsage. */
  882.     int     size;         /* Size of checkpoint region. */
  883. {
  884.     LfsSegUsage          *usagePtr = &(lfsPtr->usageArray);
  885.  
  886.     if (size < sizeof(LfsSegUsageCheckPoint)) {
  887.     panic("LfsSegUsageCheckpointUpdate bad checkpoint size.\n");
  888.     }
  889.     (*(LfsSegUsageCheckPoint *) checkPointPtr) = usagePtr->checkPoint;
  890.     return;
  891. }
  892.  
  893.  
  894. extern ReturnStatus LfsSegUsageAttach _ARGS_((Lfs *lfsPtr, 
  895.             int checkPointSize, char *checkPointPtr));
  896. extern Boolean LfsSegUsageCheckpoint _ARGS_((LfsSeg *segPtr, int flags, 
  897.             char *checkPointPtr, int *checkPointSizePtr, 
  898.             ClientData *clientDataPtr));
  899. extern void LfsSegUsageWriteDone _ARGS_((LfsSeg *segPtr, int flags, 
  900.             ClientData *clientDataPtr));
  901. extern Boolean LfsSegUsageClean _ARGS_((LfsSeg *segPtr, int *sizePtr,
  902.             int *numCacheBlocksPtr, ClientData *clientDataPtr));
  903. extern Boolean LfsSegUsageLayout _ARGS_((LfsSeg *segPtr, int flags, 
  904.             ClientData *clientDataPtr));
  905.  
  906. extern ReturnStatus LfsSegUsageDetach _ARGS_((Lfs *lfsPtr));
  907.  
  908. static LfsSegIoInterface segUsageIoInterface = 
  909.     { LfsSegUsageAttach, LfsSegUsageLayout, LfsSegUsageClean,
  910.       LfsSegUsageCheckpoint, LfsSegUsageWriteDone, LfsSegUsageDetach, 0};
  911.  
  912.  
  913. /*
  914.  *----------------------------------------------------------------------
  915.  *
  916.  * LfsSegUsageInit --
  917.  *
  918.  *    Initialize the segment usage array  data structures.  
  919.  *
  920.  * Results:
  921.  *    None
  922.  *    
  923.  * Side effects:
  924.  *
  925.  *----------------------------------------------------------------------
  926.  */
  927.  
  928. void
  929. LfsSegUsageInit()
  930. {
  931.     LfsSegIoRegister(LFS_SEG_USAGE_MOD,&segUsageIoInterface);
  932. }
  933.  
  934.  
  935. /*
  936.  *----------------------------------------------------------------------
  937.  *
  938.  * SegUsageAttach --
  939.  *
  940.  *    Attach routine for the seg usage map. Creates and initializes the
  941.  *    map for this file system.
  942.  *
  943.  * Results:
  944.  *    SUCCESS if attaching is going ok.
  945.  *
  946.  * Side effects:
  947.  *    Many
  948.  *
  949.  *----------------------------------------------------------------------
  950.  */
  951.  
  952. ReturnStatus
  953. LfsSegUsageAttach(lfsPtr, checkPointSize, checkPointPtr)
  954.     Lfs   *lfsPtr;         /* File system for attach. */
  955.     int   checkPointSize;    /* Size of checkpoint data. */
  956.     char  *checkPointPtr;     /* Data from last checkpoint before shutdown. */
  957. {
  958.     LfsSegUsage          *usagePtr = &(lfsPtr->usageArray);
  959.     LfsSegUsageCheckPoint *cp = (LfsSegUsageCheckPoint *) checkPointPtr;
  960.     ReturnStatus status;
  961.  
  962.     /*
  963.      * Allocate and fill in memory data structure for descriptor map.
  964.      */
  965.     usagePtr->params = lfsPtr->superBlock.usageArray;
  966.     usagePtr->checkPoint = *cp;
  967.     usagePtr->timeOfLastWrite = Fsutil_TimeInSeconds();
  968.     /*
  969.      * Load the stableMem and buffer using the LfsStableMem routines.
  970.      */
  971.     status = LfsStableMemLoad(lfsPtr, &(usagePtr->params.stableMem), 
  972.             checkPointSize - sizeof(LfsSegUsageCheckPoint), 
  973.             checkPointPtr + sizeof(LfsSegUsageCheckPoint), 
  974.             &(usagePtr->stableMem));
  975.     if (status != SUCCESS) {
  976.     LfsError(lfsPtr, status,"Can't loading descriptor map stableMem\n");
  977.     return status;
  978.     }
  979.     printf("LfsSegUsageAttach - logEnd <%d,%d>, numClean %d numDirty %d numFull %d\n",
  980.         cp->currentSegment, cp->currentBlockOffset,
  981.         cp->numClean, cp->numDirty,
  982.         usagePtr->params.numberSegments - cp->numClean - cp->numDirty);
  983.     return status;
  984. }
  985.  
  986. /*
  987.  *----------------------------------------------------------------------
  988.  *
  989.  * SegUsageDetach --
  990.  *
  991.  *    Detach routine for the seg usage array. Destory the
  992.  *    array for this file system.
  993.  *
  994.  * Results:
  995.  *    SUCCESS if dettach is going ok.
  996.  *
  997.  * Side effects:
  998.  *    Many
  999.  *
  1000.  *----------------------------------------------------------------------
  1001.  */
  1002.  
  1003. ReturnStatus
  1004. LfsSegUsageDetach(lfsPtr)
  1005.     Lfs   *lfsPtr;         /* File system for attach. */
  1006. {
  1007.     LfsSegUsage          *usagePtr = &(lfsPtr->usageArray);
  1008.  
  1009.     return LfsStableMemDestory(lfsPtr,     &(usagePtr->stableMem));
  1010. }
  1011.  
  1012. /*
  1013.  *----------------------------------------------------------------------
  1014.  *
  1015.  * SegUsageCheckpoint --
  1016.  *
  1017.  *    Routine to handle checkpointing of the descriptor map data.
  1018.  *
  1019.  * Results:
  1020.  *    TRUE if more data needs to be written, FALSE if this module is
  1021.  *    checkpointed.
  1022.  *
  1023.  * Side effects:
  1024.  *    Many
  1025.  *
  1026.  *----------------------------------------------------------------------
  1027.  */
  1028.  
  1029. Boolean
  1030. LfsSegUsageCheckpoint(segPtr, flags,checkPointPtr, checkPointSizePtr, 
  1031.             clientDataPtr)
  1032.     LfsSeg *segPtr;        /* Segment containing data for checkpoint. */
  1033.     char   *checkPointPtr;      /* Buffer to write checkpoint data. */
  1034.     int       flags;        /* Flags. */
  1035.     int       *checkPointSizePtr;  /* Bytes added to the checkpoint area.*/
  1036.     ClientData *clientDataPtr;
  1037. {
  1038.     LfsSegUsage          *usagePtr = &(segPtr->lfsPtr->usageArray);
  1039.     LfsSegUsageCheckPoint *cp = (LfsSegUsageCheckPoint *) checkPointPtr;
  1040.     int        size;
  1041.     Boolean    full;
  1042.  
  1043.     *cp = usagePtr->checkPoint;
  1044.     size = sizeof(LfsSegUsageCheckPoint);
  1045.  
  1046.     full = LfsStableMemCheckpoint(segPtr, checkPointPtr + size, flags,
  1047.         checkPointSizePtr, clientDataPtr,
  1048.         &(usagePtr->stableMem));
  1049.     if (!full) { 
  1050.     *checkPointSizePtr = (*checkPointSizePtr) + size;
  1051.     }
  1052.     return full;
  1053.  
  1054. }
  1055.  
  1056. /*
  1057.  *----------------------------------------------------------------------
  1058.  *
  1059.  * SegUsageWriteDone --
  1060.  *
  1061.  *    Routine to handle finishing of a checkpoint.
  1062.  *
  1063.  * Results:
  1064.  *    None
  1065.  *
  1066.  * Side effects:
  1067.  *    Many
  1068.  *
  1069.  *----------------------------------------------------------------------
  1070.  */
  1071.  
  1072. void
  1073. LfsSegUsageWriteDone(segPtr, flags, clientDataPtr)
  1074.     LfsSeg *segPtr;        /* Segment containing data for checkpoint. */
  1075.     int       flags;        /* Flags for checkpoint */
  1076.     ClientData *clientDataPtr;
  1077. {
  1078.     LfsSegUsage          *usagePtr = &(segPtr->lfsPtr->usageArray);
  1079.  
  1080.     LFS_STATS_ADD(segPtr->lfsPtr->stats.segusage.blocksWritten, 
  1081.         (LfsSegSummaryBytesLeft(segPtr) / sizeof(int)));
  1082.     LfsStableMemWriteDone(segPtr, flags, clientDataPtr, 
  1083.               &(usagePtr->stableMem));
  1084.     return;
  1085.  
  1086. }
  1087.  
  1088.  
  1089. /*
  1090.  *----------------------------------------------------------------------
  1091.  *
  1092.  * LfsSegUsageClean --
  1093.  *
  1094.  *    Routine to handle cleaning of descriptor map data.
  1095.  *
  1096.  * Results:
  1097.  *    TRUE if more data needs to be written, FALSE if this module is
  1098.  *    happy for the time being.
  1099.  *
  1100.  * Side effects:
  1101.  *    
  1102.  *
  1103.  *----------------------------------------------------------------------
  1104.  */
  1105.  
  1106. Boolean
  1107. LfsSegUsageClean(segPtr, sizePtr, numCacheBlocksPtr, clientDataPtr)
  1108.     LfsSeg *segPtr;    /* Segment containing data to clean. */
  1109.     int *sizePtr;        /* Size of cleaning. */
  1110.     int *numCacheBlocksPtr;
  1111.     ClientData *clientDataPtr;
  1112. {
  1113.     LfsSegUsage          *usagePtr = &(segPtr->lfsPtr->usageArray);
  1114.     Boolean    full;
  1115.  
  1116.     full =  LfsStableMemClean(segPtr, sizePtr, numCacheBlocksPtr, clientDataPtr,
  1117.             &(usagePtr->stableMem));
  1118.  
  1119.     LFS_STATS_ADD(segPtr->lfsPtr->stats.segusage.blocksCleaned, 
  1120.         *sizePtr/usagePtr->stableMem.params.blockSize);
  1121.     return full;
  1122.  
  1123. }
  1124.  
  1125.  
  1126.  
  1127. /*
  1128.  *----------------------------------------------------------------------
  1129.  *
  1130.  * LfsSegUsageLayout --
  1131.  *
  1132. *    Routine to handle layingout of segUsage data.
  1133.  *
  1134.  * Results:
  1135.  *    TRUE if more data needs to be written, FALSE if this module is
  1136.  *    happy for the time being.
  1137.  *
  1138.  * Side effects:
  1139.  *    
  1140.  *
  1141.  *----------------------------------------------------------------------
  1142.  */
  1143.  
  1144. Boolean
  1145. LfsSegUsageLayout(segPtr, flags, clientDataPtr)
  1146.     LfsSeg *segPtr;    /* Segment containing data to clean. */
  1147.     int flags; /* Layout flags. */
  1148.     ClientData *clientDataPtr;
  1149. {
  1150.     LfsSegUsage          *usagePtr = &(segPtr->lfsPtr->usageArray);
  1151.  
  1152.     if ((flags & LFS_CLEANING_LAYOUT) != 0) {
  1153.     return FALSE;
  1154.     }
  1155.     return  LfsStableMemLayout(segPtr, flags, 
  1156.                 clientDataPtr, &(usagePtr->stableMem));
  1157. }
  1158.  
  1159.